/************************************************************************************
* SLDataRetriever.cpp                                                               *
*                                                                                   *
* Copyright (C) 2011 Varuna L Amachi                                                *
*                                                                                   *
* This program is free software; you can redistribute it and/or modify              *
* it under the terms of the GNU General Public License as published by              *
* the Free Software Foundation; either version 2 of the License, or any             *
* later version.                                                                    *
*                                                                                   *
* This program is distributed in the hope that it will be useful, but               *
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY        *
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for       *
* more details. You should have received a copy of the GNU General Public           *
* License along with this program; if not, write to the Free Software Foundation,   *
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA                       *
*                                                                                   *
*************************************************************************************/

#include "SLDataRetriever.h"

#include <QSqlQuery>

#include "common/Utils.h"
#include "common/CommonTypes.h"
#include "common/YLog.h"

using namespace Phonon;

SLDataRetriever::SLDataRetriever() {

}
//trackId TEXT PRIMERY KEY
//trackPath TEXT
//trackName TEXT
//artistName TEXT
//albumName TEXT
//trackDate TEXT
//genre TEXT
//trackNum TEXT
//duration INTEGER
//bitrate INTEGER
//sampleRate INTEGER
//channels INTEGER
//rating INTEGER
//numPlays INTEGER

QHash<QString, CollectorItem*>* SLDataRetriever::retrieveCollection(QSqlDatabase* database) {
    QString statement("SELECT * FROM Collection;");
    QSqlQuery *query = getQuery(database);
    QHash<QString, CollectorItem*> *collection = new QHash<QString, CollectorItem*>();
    query->prepare(statement);
    if(query->exec()) {
        while(query->next()) {
            CollectorItem *item = getCollectorItemFromQuery(query);
            if(item != NULL) {
                collection->insert(item->trackId(), item);
            }
        }
    }
    YLog::logQuery("retrieveCollection", query);
    delete query;
    return collection;
}


QList<QString>* SLDataRetriever::retrieveRecentlyAdded(QSqlDatabase* database) {
    QString statement("SELECT trackId FROM RecentAdditions;");
    QSqlQuery *query = getQuery(database);
    QList<QString>* items = new QList<QString>();
    query->prepare(statement);
    if (query->exec()) {
        while(query->next()) {
            items->append(query->value(0).toString());
        }
    }
    YLog::logQuery("retrieveRecentlyAdded", query);
    delete query;
    return items;
}


//PlaylistInfo {
//  playlistName TEXT PRIMARY KEY
//  creationTime INTEGER
//  lastModified INTEGER
//  rating       INTEGER
//  comment      TEXT
//}
QList<SavedPlaylist*>* SLDataRetriever::retrievePlaylists(QSqlDatabase* database) {
    QString statement("SELECT * FROM PlaylistInfo;");
    QSqlQuery* query = getQuery(database);
    query->prepare(statement);
    QList<SavedPlaylist*>* playlists = new QList<SavedPlaylist*>();
    if(query->exec()) {
        while(query->next()) {
            QString name      = query->value(0).toString();
            quint64 crtTime   = (quint64) query->value(1).toULongLong();
            quint64 modTime   = (quint64) query->value(2).toULongLong();
            int     rating    = query->value(3).toInt();
            QString comment   = query->value(4).toString();
            SavedPlaylist* pl = new SavedPlaylist(
                                    name,
                                    QDateTime::fromMSecsSinceEpoch(crtTime),
                                    QDateTime::fromMSecsSinceEpoch(modTime),
                                    Utils::getMediaRating(rating),
                                    comment);
            playlists->append(pl);
        }
    }
    YLog::logQuery("retrievePlaylists", query);
    delete query;
    return playlists;
}


QList<QString> *SLDataRetriever::retrieveHistory(QSqlDatabase *database) {
    QString statement("SELECT trackId FROM PlayHistory");
    QSqlQuery *query = getQuery(database);
    query->prepare(statement);
    QList<QString> *history = new QList<QString>();
    if(query->exec()) {
        while(query->next()) {
            history->append(query->value(0).toString());
        }
    }
    YLog::logQuery("retrieveHistory", query);
    delete query;
    return history;
}


quint64 SLDataRetriever::retrievePlayedTime(QString &trackId, QSqlDatabase *database) {
    QString statement("SELECT lastPlayedTime FROM PlayHistory WHERE trackId = ?");
    QSqlQuery *query = getQuery(database);
    query->prepare(statement);
    query->addBindValue(trackId);
    bool result = query->exec();
    YLog::logQuery("retrievePlayedTime", query);
    if(result) {
        query->next();
        quint64 time = query->value(0).toULongLong();
        delete query;
        return time;
    }
    delete query;
    return 0;
}



quint64 SLDataRetriever::retrieveAddedTime(QString &trackId, QSqlDatabase *database) {
    QString statement("SELECT addedTime  FROM RecentAdditions WHERE trackId = ?");
    QSqlQuery *query = getQuery(database);
    query->prepare(statement);
    query->addBindValue(trackId);
    bool result = query->exec();
    YLog::logQuery("retrieveAddedTime", query);
    if(result) {
        query->next();
        quint64 time = query->value(0).toULongLong();
        delete query;
        return time;
    }
    delete query;
    return 0;
}


QHash<QString, QVariant>* SLDataRetriever::retrieveSettings(QSqlDatabase* database) {
    QString statement("SELECT * FROM Settings;");
    QSqlQuery *query = getQuery(database);
    query->prepare(statement);
    QHash<QString, QVariant> *settings = new QHash<QString, QVariant>();
    if(query->exec()) {
        while(query->exec(statement)) {
            settings->insert(query->value(0).toString(), query->value(1));
        }
    }
    YLog::logQuery("retrieveSettings", query);
    delete query;
    return settings;
}


QList<QString> *SLDataRetriever::retrieveTrackIdsForPlaylist(QString playlistName,
                                                    QSqlDatabase *database) {
    QString statement("SELECT trackId FROM Playlists WHERE playlistName = ");
    statement.append(playlistName).append(";");
    QSqlQuery *query = getQuery(database);
    query->prepare(statement);
    QList<QString> *trackIds = new QList<QString>();
    if(query->exec()) {
        while(query->next()) {
            trackIds->append(query->value(0).toString());
        }
    }
    YLog::logQuery("retrieveTrackIdsForPlaylist", query);
    delete query;
    return trackIds;
}



MediaRating SLDataRetriever::getRatingFor(QString trackId, QSqlDatabase* database) {
    QString statement("SELECT rating FROM Collection WHERE trackId = ");
    statement.append(trackId).append(";");
    QSqlQuery *query = getQuery(database);
    query->prepare(statement);
    MediaRating rating = None;
    if(query->exec()) {
        rating = Utils::getMediaRating(query->value(0).toInt());
    }
    YLog::logQuery("getRatingFor", query);
    delete query;
    return rating;
}


int SLDataRetriever::getPlayCountFor(QString trackId, QSqlDatabase* database) {
    QString statement("SELECT numPlays FROM Collection WHERE trackId = ");
    statement.append(trackId).append(";");
    QSqlQuery *query = getQuery(database);
    int numPlays = 0;
    if(query->exec(statement)) {
        numPlays = query->value(0).toInt();
    }
    YLog::logQuery("getPlayCountFor", query);
    delete query;
    return numPlays;
}



CollectorItem* SLDataRetriever::getCollectorItemFromQuery(QSqlQuery *query) {
    QString trackId   = query->value(0).toString();
    QString trackPath = query->value(1).toString();
    QString trackName = query->value(2).toString();
    QString artistName= query->value(3).toString();
    QString albumName = query->value(4).toString();
    QString trackDate = query->value(5).toString();
    QString genre     = query->value(6).toString();
    QString comment   = query->value(7).toString();
    int     trackNum  = query->value(8).toInt();
    int     duration  = query->value(9).toInt();
    int     bitRate   = query->value(10).toInt();
    int     sampleRate= query->value(11).toInt();
    int     channels  = query->value(12).toInt();
    MediaRating rating= Utils::getMediaRating(query->value(13).toInt());
    int     numPlays  = query->value(14).toInt();
    QString tags      = query->value(15).toString();

    if(QFile(trackPath).exists()) {
        MediaSource* source = new MediaSource(trackPath);
        CollectorItem* item = new CollectorItem(trackId, source);
        item->setMetaData(trackName,
                          artistName,
                          albumName,
                          trackDate,
                          genre,
                          comment,
                          trackNum,
                          duration,
                          bitRate,
                          sampleRate,
                          channels);
        item->setPlayCount(numPlays);
        item->setRating(rating);
        item->setTags(tags);
        return item;
    }
    return NULL;
}


QSqlQuery *SLDataRetriever::getQuery(QSqlDatabase *database) {
    return database != NULL ? new QSqlQuery(*database) : new QSqlQuery();
}
